<?php
/**
 * Created by .
 * User: luogan
 * Date: 2021/12/23
 */
declare(strict_types=1);

namespace App\Middleware;

use App\Exception\AuthException;
use App\Exception\TokenException;
use App\Service\AuthMenuService;
use Hyperf\Utils\Context;
use HyperfExt\Jwt\Contracts\JwtFactoryInterface;
use HyperfExt\Jwt\Exceptions\JwtException;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\Di\Annotation\Inject;
use Redis;

class AuthMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;


    /**
     * @Inject
     * @var AuthMenuService
     */
    private $authMenuService;

    /**
     * @var Redis
     */
    protected $redis;


    /**
     * @Inject
     * @var JwtFactoryInterface
     */
    private $jwtFactoryInterface;

    //跳过验证的url
    public static $ignore = ['v1/admin/login','swagger'];

    public function __construct(ContainerInterface $container)
    {
        $this->redis = $container->get(Redis::class);
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $response = Context::get(ResponseInterface::class);
        $response = $response->withHeader('Access-Control-Allow-Origin', '*')
            ->withHeader('Access-Control-Allow-Credentials', 'true')
            ->withHeader('Access-Control-Allow-Headers', 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization');
        Context::set(ResponseInterface::class, $response);
        if ($request->getMethod() == 'OPTIONS') {
            return $response;
        }
        $currUrl = trim($request->getUri()->getPath(), '/');
        if (in_array($currUrl, self::$ignore)) {
            $result = $handler->handle($request);
            return $result;
        }
        //验证token
        $payload = $this->checkToken();
        //验证是否有访问菜单的权限
       // $this->checkAuth($payload['admin_id'],$currUrl);
        //验证是否有当前url访问权限
        $result = $handler->handle($request);
        return $result;

    }

    /**
     * 验证token
     * @return \HyperfExt\Jwt\Payload
     * @throws JwtException
     */
    private function checkToken()
    {
        $jwt = $this->jwtFactoryInterface->make();
        //判断是否有token
        try {
            $token = $jwt->parseToken();
        }catch (JwtException $jwtException){
            throw new TokenException('没有登录，请重新登录');
        }
        //验证token
        $check_token = $token->check();
        if (!$check_token){
            throw new TokenException('登录异常或者失效，请重新登陆');
        }
        //获取token包含信息
        $payload = $token->getPayload();
        return $payload;
    }

    /**
     * 验证菜单权限
     * @param $adminID
     * @param $action
     * @return bool
     */
    private function checkAuth($adminID,$action){

        $auth = $this->authMenuService->getAuthCache($adminID);
        foreach ($auth as $k => $v) {
            if ($k == md5($action)){
                return true;
            }
        }
        throw new AuthException('没有访问权限');
    }
}
